home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / util / libs / graphics3d.lha / src / library / graphics3df1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-16  |  29.0 KB  |  1,205 lines

  1. /*
  2. **      $VER: graphics3Df1.c 11.00 (31.12.98)
  3. **
  4. **      Main functions for graphics3D.library
  5. **    PARTE #2
  6. **
  7. **      (C) Copyright 97,98 Patrizio Biancalani
  8. **      All Rights Reserved.
  9. **      
  10. **    Note: this code is a partially traslate from the blitzbasic 3d graphics engine 
  11. **          V 0.9 of Maciej R. Gorny.
  12. **
  13. */
  14.  
  15. #include <exec/types.h>
  16. #include <exec/memory.h>
  17. #include <proto/exec.h>
  18. #include <dos/dos.h>
  19. #include <proto/intuition.h>
  20. #include <intuition/intuition.h>
  21. #include <intuition/screens.h>
  22.  
  23. #include <graphics/rastport.h>
  24. #include <graphics/clip.h>
  25. #include <graphics/regions.h>
  26. #include <graphics/gfx.h>
  27. #include <graphics/gfxmacros.h>
  28. #include <graphics/layers.h>
  29.  
  30. #include "graphics3Dc.h"
  31. #include "graphics3D.h"
  32. #include "graphics3D2d.h"
  33. #include "graphics3Df_proto.h"
  34. #include "graphics3D2d_proto.h"
  35.  
  36.  /* Please note, that &Graphics3dBase always resides in register __a6 as well,
  37.     but if we don't need it, we need not reference it here.
  38.  
  39.     Also note, that registers a0, a1, d0, d1 always are scratch registers,
  40.     so you usually should only *pass* parameters there, but make a copy
  41.     directly after entering the function. To avoid problems of kind
  42.     "implementation defined behaviour", you should make a copy of A6 too,
  43.     when it is actually used.
  44.  
  45.     In this example case, scratch register saving would not have been 
  46.     necessary (since there are no other function calls inbetween), but we 
  47.     did it nevertheless.
  48.   */
  49.  
  50. extern void buildlookuptables(struct ambient3d *in);
  51. extern void createworldtocamera(struct ambient3d *in);
  52. extern void recalcobj(struct ambient3d *in);
  53. extern long int t_removeobject(struct ambient3d *in);
  54. extern void localtoworld(struct ambient3d *in);
  55. extern void worldtocamera(struct ambient3d *in);
  56. extern void removebackfacesandshade(struct ambient3d *in);
  57. extern void clipobject3d(struct ambient3d *in);
  58. extern void generatepolylist(struct ambient3d *in);
  59. extern struct objectnode *resetobj(struct ambient3d *in);
  60. extern struct objectnode *nextobj(struct ambient3d *in);
  61. extern struct objectnode *pobj(struct ambient3d *in);
  62. extern void aggobj(struct ambient3d *in);
  63. extern void matidentity4x4(struct matrix4x4 *imatrix); 
  64. extern void matzero4x4(struct matrix4x4 imatrix);
  65. extern void matcopy4x4(struct matrix4x4 *s_m,struct matrix4x4 *d_m);
  66. extern void matmult4x4(struct matrix4x4 *a,struct matrix4x4 *b,
  67.         struct matrix4x4 *r);
  68. extern void matmult4x4s(struct matrix4x4 *a,struct matrix4x4 *b,
  69.         struct matrix4x4 *r);
  70. extern void matmult1x4s(struct matrix1x4 *a,struct matrix4x4 *b,
  71.         struct matrix1x4 *r);
  72. extern void makevector3d(struct vertex *a,struct vertex *b,
  73.          struct vector *result);
  74. extern long int vectormag3d(struct vector *a);
  75. extern void normalpol(struct vertex *v0,struct vertex *v1,
  76.      struct vertex *v2,struct vector *normal);
  77. extern long int dotproduct(struct vector *u,struct vector *v);
  78. extern long int sqri(long int v);
  79. extern long int abs(long int val);
  80. extern void qsort(long int lo0,long int hi0,long int *pol,long int *count);
  81. extern void paintpol(struct ambient3d *in,long int *iwp,
  82.     long int total_polys,long int colb); 
  83. extern long int quicksort(long int len,long int *pol);
  84.  
  85. /**********************************************************/
  86.  
  87. /****************************************************
  88.  ** Routin per la gestione della grafica, in stile **
  89.  ** 2.0                                            ** 
  90.  ** (c) 1994 BIANCA HARD&SOFT Vers:1.00            **
  91.  ****************************************************/
  92.  
  93. /************ FUNZIONI 3D ********************************/
  94.  
  95. /** macro ad uso interno e provvisorio **/
  96. #define mver(val) (val*sizeof(Svertex)+10)
  97. #define mobj(val) (val*sizeof(Sobjectnode)+5)
  98. #define mplf(val) (val*sizeof(long int)+5)
  99. #define mtmp(val) (val*sizeof(Spolytemp)+5)
  100. #define tang (361*4+5)
  101. /****************************************/
  102.  
  103. /*** prototipi solo locali ***/
  104. long int read_iff(long int f,unsigned char *campo);
  105. long int read_r(long int f,long int comp,short int ll,unsigned char *bf);
  106. /*****************************/
  107.  
  108. /********************************************
  109.  ** cambia il modo di visualizzazione      **
  110.  ** dell'oggetto attualmente selezionato.  **
  111.  ********************************************
  112.  *** INPUT :                    *
  113.  * in  -> valore >0 restituito da display3d.*
  114.  * modo-> modalita' di visualizzazione      *
  115.  *        oggetti.                *
  116.  *        WIREF= wire frame                 *
  117.  *        SOLID= solid shade               *
  118.  *        FLAT = flat shading            *
  119.  *      GORAUD = goraud shading        *
  120.  *** OUTPUT:                     *
  121.  * >0 tutto ok.                    *
  122.  * =0 valore non valido.            *
  123.  ********************************************/
  124. long int GD_changeviewmodeobj(in,modo)
  125. REG(a0)struct ambient3d *in;
  126. REG(d0)long int modo;
  127. {
  128. struct objectnode *obj;
  129. char md;
  130.  
  131. md=0x0F & modo;
  132.  
  133. if (md!=WIREF AND md!=SOLID AND md!=FLAT AND md!=GORAUD) return(0);
  134.  
  135.  
  136. obj=pobj(in);
  137.  
  138. obj->shade=modo;
  139. obj->trasf|=0x01;
  140.  
  141. return(1);
  142. }
  143.  
  144. /************************************************
  145.  ** Trova le eventuali collisioni degli oggetti**
  146.  ** con quello attuale.                   **
  147.  ************************************************
  148.  **** INPUT :                        *
  149.  * in -> valore > 0 restituito da display3d.    *
  150.  * n  -> n# massimo oggetti da rilevare.    *
  151.  * buf-> puntatore ad array di long int di n    *
  152.  *     elementi, dove mettere id degli oggetti*
  153.  *     in collisione.                *
  154.  **** OUTPUT:                    *
  155.  * n# oggetti effettivamente rilevati.        *
  156.  * =0 nessuno.                    *
  157.  **** NOTA:                    *
  158.  * il valore ritornato puo' essere anche > di n *
  159.  ************************************************/
  160. long int GD_colldetect(in,n,buf)
  161. REG(a0)struct ambient3d *in;
  162. REG(d0)long int n;
  163. REG(a1)long int *buf;
  164. {
  165. long int minx,miny,minz,maxx,maxy,maxz;
  166. long int xmn,ymn,zmn,xmx,ymx,zmx;
  167. struct objectnode *obj,*ob;
  168. long int i,ct,obja;
  169.  
  170. ct=0;
  171. if (in->total_objects==NULL) return(0);
  172.  
  173. obj=pobj(in);
  174. obja=in->attuale;
  175.  
  176. minx=obj->xmin+obj->worldposx;
  177. miny=obj->ymin+obj->worldposy;
  178. minz=obj->zmin+obj->worldposz;
  179. maxx=obj->xmax+obj->worldposx;
  180. maxy=obj->ymax+obj->worldposy;
  181. maxz=obj->zmax+obj->worldposz;
  182.  
  183. ob=resetobj(in);
  184.  
  185. do
  186.     {
  187.     if (ob->id==obj->id OR ob->state==NULL) continue;
  188.     xmn=ob->xmin+ob->worldposx;
  189.     ymn=ob->ymin+ob->worldposy;
  190.     zmn=ob->zmin+ob->worldposz;
  191.     xmx=ob->xmax+ob->worldposx;
  192.     ymx=ob->ymax+ob->worldposy;
  193.     zmx=ob->zmax+ob->worldposz;
  194.     /* test se i due oggetti non collidono */
  195.     if (minx>=xmx OR maxx<=xmn OR miny>=ymx OR maxy<=ymn 
  196.         OR minz>=zmx OR maxz<=zmn) continue;
  197.     if (ct<n) buf[ct]=ob->id;
  198.     ct++;
  199.     }while((ob=nextobj(in))!=NULL);
  200.  
  201. in->attuale=obja;
  202. return(ct);
  203.  
  204. }
  205.  
  206. /************************************************
  207.  ** trova l'oggetto e il poligono al cui       **
  208.  ** interno risiede il punto dato.           **
  209.  ** ignora i poligoni con meno di 3 lati.      **
  210.  ************************************************
  211.  *** INPUT :                        *
  212.  * in -> valore > 0 restituito da display3d.    *
  213.  * np -> puntatore a long, dove mettere n# pol. *
  214.  *       al cui interno risiede il punto.    *
  215.  * xp -> coordinata x punto dato nella finestra * 
  216.  *     in cui e' visualizzata la scena.    *
  217.  *     (valore intero).            *  
  218.  * yp -> coordinata y punto dato nella finestra * 
  219.  *     in cui e' visualizzata la scena.    *
  220.  *     (valore intero).            *  
  221.  *** OUTPUT:                    *
  222.  * = 0 nessun oggetto trovato.            *
  223.  *     (in questo caso valore in np senza sign.)*
  224.  * > 0 valore identificativo oggetto trovato.   *
  225.  *** NOTA:                    *
  226.  * L'algoritmo che ho usato sembra funzioni ma  *
  227.  * e' stato trovato in modo del tutto empirico  *
  228.  * se qualcuno mi sa spiegare perche' funzioni  *
  229.  * e' il benvenuto.                *
  230.  ************************************************/
  231. long int GD_pickobj(in,np,xp,yp)
  232. REG(a0)struct ambient3d *in;
  233. REG(a1)long int *np;
  234. REG(d0)long int xp;
  235. REG(d1)long int yp;
  236. {
  237. struct polytemp *plt;
  238. long int *ip,id,i,ris;
  239. long int zz,x,y,xm,ym,x1,x2,x3,y1,y2,y3;
  240.  
  241. ip=in->iwpolys;
  242. if (ip==NULL) return(0);
  243. ris=0;
  244. i=in->total_polys-1;
  245.  
  246. x=xp-in->minx;
  247. y=yp-in->miny;
  248. zz=0x7FFFFFFF;
  249.  
  250. for (i=0 ; i<in->total_polys; i++)
  251.     {
  252.     plt=(struct polytemp *)ip[i];
  253.     if (plt->numpoints<3) goto prossimo;
  254. /* traslo origini poligono su punto dato */
  255.     x1=plt->x1-x;
  256.     y1=plt->y1-y; 
  257.     x2=plt->x2-x;
  258.     y2=plt->y2-y; 
  259.     x3=plt->x3-x;
  260.     y3=plt->y3-y; 
  261. /* calcolo massimo x e y del triangolo (in valore assoluto)*/ 
  262.     xm=abs(x1);
  263.     if (abs(x2)>xm) xm=abs(x2);
  264.     if (abs(x3)>xm) xm=abs(x3);
  265.     ym=abs(y1);
  266.     if (abs(y2)>ym) ym=abs(y2);
  267.     if (abs(y3)>ym) ym=abs(y3);
  268. /* sommo gli assi dei tre vertici tra loro */
  269.     x1=abs(x1+x2+x3);
  270.     y1=abs(y1+y2+y3);
  271. /* test se risultato in valore assoluto maggiore dei val. massimi per x e y*/
  272. /* se no, punto interno altrimenti esterno */        
  273.     if (x1<=xm AND y1<=ym AND zz>plt->svalue) 
  274.         {
  275.         ris=plt->obj;
  276.         np[0]=plt->npol;
  277.         zz=plt->svalue;
  278.         }
  279. /* se poligono composto di 4 lati ripeto il test per l'altro triangolo */
  280.     if (plt->numpoints=4)
  281.         {
  282.     /* traslo origini poligono su punto dato */
  283.         x1=plt->x3-x;
  284.         y1=plt->y3-y; 
  285.         x2=plt->x4-x;
  286.         y2=plt->y4-y; 
  287.         x3=plt->x1-x;
  288.         y3=plt->y1-y; 
  289.         xm=abs(x1);
  290.         if (abs(x2)>xm) xm=abs(x2);
  291.         if (abs(x3)>xm) xm=abs(x3);
  292.         ym=abs(y1);
  293.         if (abs(y2)>ym) ym=abs(y2);
  294.         if (abs(y3)>ym) ym=abs(y3);
  295.         x1=abs(x1+x2+x3);
  296.         y1=abs(y1+y2+y3);
  297.         if (x1<=xm AND y1<=ym AND zz>plt->svalue) 
  298.             {
  299.             ris=plt->obj;
  300.             np[0]=plt->npol;
  301.             zz=plt->svalue;
  302.             }
  303.         }
  304.     prossimo:
  305.     }
  306.  
  307. return(ris);
  308.  
  309. }
  310.  
  311. /************************************************
  312.  ** aggiunge una nuova texture map all'elenco  **
  313.  ************************************************
  314.  *** INPUT :                    *
  315.  * in -> valore >0 restituito da display3d.    *
  316.  * dx -> larghezza texture map in pixel.    *
  317.  * dy -> altezza texture map in pixel.        *
  318.  * buf -> puntatore ad area con chunky buffer   *
  319.  *        della texturemap (si usera' dx e dy)  *
  320.  *** OUTPUT:                    *
  321.  * = 0 aggiunta fallita.            *
  322.  * > 0 indirizzo descrittore nuova texture.     *
  323.  ************************************************/
  324. long int GD_newtmap(in,dx,dy,buf)
  325. REG(a0)struct ambient3d *in;
  326. REG(d0)short int dx;
  327. REG(d1)short int dy;
  328. REG(a1)unsigned char *buf;
  329. {
  330. long int i,ct,ln,ris,nc;
  331. struct buftmap *btm;
  332. unsigned char *buf1;
  333. #ifdef DEBUG
  334. char dbg[100];
  335. #endif
  336.  
  337. btm=in->graf->a_tmap;
  338. nc=in->graf->n_color;
  339.  
  340. /* se la tabella per le texture non e' presente esco subito con 0 */
  341. if (btm==NULL) return(NULL);
  342.  
  343. i=0;
  344. while(i<TTMAP AND btm[i].chunky!=NULL) i++;
  345.  
  346. #ifdef DEBUG
  347. sprintf(dbg,"indice=%ld chunky=%ld\n",i,btm[i].chunky);
  348. write_dbg(dbg);
  349. #endif
  350.  
  351. if (i<TTMAP)
  352.     {
  353.     ln=dx*dy+100;
  354.     buf1=(unsigned char *)AllocMem(ln,NULL);
  355.     if (buf1==NULL) return (0L);
  356.     btm[i].chunky=buf1;
  357.     btm[i].lung=ln;
  358.     btm[i].larg=dx;
  359.     btm[i].alt=dy;
  360.     for(ct=0 ; ct<dx*dy ;ct++) 
  361.         {
  362.         if (buf[ct]<nc)
  363.             {
  364.             buf1[ct]=buf[ct];    
  365.             }
  366.         else
  367.             {
  368.             buf1[ct]=nc-1;
  369.             }
  370.         }
  371. #ifdef DEBUG
  372. sprintf(dbg,"id=%ld lung=%ld larg=%ld chunky=%ld\n",&(btm[i]),btm[i].lung,btm[i].larg,
  373.     btm[i].chunky);
  374. write_dbg(dbg);
  375. #endif
  376.     ris=(long int)&btm[i];
  377. #ifdef DEBUG
  378. sprintf(dbg,"ris=%ld\n",ris);
  379. write_dbg(dbg);
  380. #endif
  381.     return(ris);
  382.     }
  383.  
  384. return(0L);
  385. }
  386.  
  387. /************************************************
  388.  ** aggiunge una nuova texture map all'elenco  **
  389.  ** leggendola da un file IFF_ILBM.           **
  390.  ************************************************
  391.  *** INPUT :                    *
  392.  * in -> valore >0 restituito da display3d.    *
  393.  * name -> a stringa con nome file da leggere.  *
  394.  *       (indicare il path completo).        *
  395.  *** OUTPUT:                    *
  396.  * = 0 aggiunta fallita.            *
  397.  * > 0 indirizzo descrittore nuova texture.     *
  398.  ************************************************/
  399. long int GD_newtmapf(in,name)
  400. REG(a0)struct ambient3d *in;
  401. REG(a1)unsigned char *name;
  402. {
  403. long int depth,lb,comp,ris,y,yy,dx,dy,fin,i,len;
  404. short int *ps,id,sc;
  405. unsigned char mk,val,*tb1,*tb,*buf;
  406. #ifdef DEBUG
  407. unsigned char dbg[100];
  408. #endif
  409.  
  410. tb=in->temp;
  411. ps=(short int *)tb;
  412. ris=0L;
  413. fin=Open(name,MODE_OLDFILE);
  414. if (fin==NULL) return(0L);
  415.  
  416. /* leggo Header IFF */
  417. Read(fin,tb,12);
  418. if (tb[0]!='F' OR tb[1]!='O' OR tb[2]!='R' OR tb[3]!='M') goto abort_err;
  419. if (tb[8]!='I' OR tb[9]!='L' OR tb[10]!='B' OR tb[11]!='M') goto abort_err;
  420.  
  421. /* leggo primo campo con dati immagine */
  422. i=read_iff(fin,"BMHD");
  423. if (i==0) goto abort_err;
  424. /* leggo i dati dell'immagine */
  425. len=Read(fin,tb,i);
  426. if (len!=i) goto abort_err;
  427. dx=ps[0];
  428. dy=ps[1];
  429. depth=tb[8];
  430. comp=tb[10];
  431. lb=(dx+7)/8;
  432. if (depth>8) goto abort_err;
  433. if (dx>9000) goto abort_err;
  434.  
  435. #ifdef DEBUG
  436. sprintf(dbg,"IMG=%s - ",name);
  437. write_dbg(dbg);
  438. sprintf(dbg,"dx=%ld dy=%ld depth=%ld comp=%ld\n",dx,dy,depth,comp);
  439. write_dbg(dbg);
  440. #endif
  441.  
  442. /* apro un buffer delle dimensioni dell'immagine */
  443. buf=AllocMem(dx*dy+100,NULL);
  444. if (buf==NULL) goto abort_err;
  445.  
  446. /* leggo il campo col corpo dell'immagine */
  447. i=read_iff(fin,"BODY");
  448. if (i==0) goto abort_err1;
  449. #ifdef DEBUG
  450. sprintf(dbg,"len=%ld\n",i);
  451. write_dbg(dbg);
  452. #endif
  453.  
  454. /* leggo il corpo dell'immagine */
  455. len=0;
  456. for(y=0 ; y<dy ;y++)
  457.     {
  458.     tb1=tb;
  459.     for(yy=0 ; yy<depth ; yy++)
  460.         {
  461.     /* leggo una linea con o senza compressione */    
  462.         if (read_r(fin,comp,lb,tb1)==NULL) goto abort_err1;
  463.         tb1+=lb;
  464.         }
  465.     mk=0x80;    /* maschera per bit */
  466.     sc=7;        /* n# di shift da effettuare */
  467.     /* conversione riga da planar a chunky */
  468.     for(i=0; i<dx; i++)
  469.         {
  470.         val=0;
  471.         tb1=tb;
  472.         id=i/8;
  473.         for(yy=0; yy<depth ;yy++)
  474.             {
  475.             val+=((mk & tb1[id])>>sc)<<yy;
  476.             tb1+=lb;
  477.             }
  478.         mk=mk>>1;
  479.         sc--;
  480.         if (sc<0)
  481.             {
  482.             mk=0x80;
  483.             sc=7;
  484.             }
  485.         buf[len++]=val;
  486. /*
  487. #ifdef DEBUG
  488. sprintf(dbg,"%ld,",val);
  489. write_dbg(dbg);
  490. #endif
  491. */
  492.         }
  493. /*
  494. #ifdef DEBUG
  495. sprintf(dbg,"\n");
  496. write_dbg(dbg);
  497. #endif
  498. */
  499.     }
  500.  
  501. /* aggiungo chunky display map ottenuta alla lista delle texture map */
  502. ris=GD_newtmap(in,dx,dy,buf);
  503.  
  504. abort_err1:
  505. FreeMem(buf,dx*dy+100);
  506.  
  507. abort_err:
  508. Close(fin);
  509. return(ris);
  510. }
  511.  
  512. /************************************************
  513.  ** Si posiziona all'inizio dei dati di un     **
  514.  ** campo iff.                       **
  515.  ************************************************
  516.  *** INPUT :                    *
  517.  * f -> id. file da leggere .            *
  518.  * campo -> puntatore a stringa con nome campo  *
  519.  *        (usa solo i primi 4 bytes)        *
  520.  *** OUTPUT:                    *
  521.  * ==0 -> errore o campo vuoto.            *
  522.  * !=0 -> lunghezza dati nel campo.        *
  523.  ************************************************/
  524. long int read_iff(long int f,unsigned char *campo)
  525. {
  526. long int len,*ii;
  527. unsigned char buf[10];
  528.  
  529. len=0;
  530.  
  531. /* mi sposto sicuramente all'inizio utile del file */
  532. Seek(f,12,OFFSET_BEGINNING);
  533.  
  534. /* leggo testata + lunghezza campo fino ad un errore o al momento in cui 
  535.    non trovo quella cercata*/
  536. while(len==0)
  537.     {
  538.     if (Read(f,buf,8)!=8) break;
  539.     ii=(long int *)&buf[4];
  540.     /* test se campo cercato */
  541.     if (buf[0]==campo[0] AND buf[1]==campo[1] AND buf[2]==campo[2] AND buf[3]==campo[3])
  542.         {
  543.         len=ii[0];
  544.         }
  545.     else
  546.         {
  547.     /* altrimenti salto a successivo */
  548.         Seek(f,ii[0],OFFSET_CURRENT);
  549.         }
  550.     }
  551.  
  552. return(len);
  553. }
  554. /************************************************
  555.  ** leggo una riga con eventuale comp. byterun **
  556.  ** e la scrivo nel buffer.               **
  557.  ************************************************/
  558. long int read_r(long int f,long int comp,short int ll,unsigned char *bf)
  559. {
  560. char flag[2];
  561. long int i,l;
  562.  
  563. #ifdef DEBUG
  564. char dbg[100];
  565. #endif
  566.  
  567. if (comp==0)
  568.     {
  569.     if (Read(f,bf,ll)!=ll) return(0);
  570.     }
  571. else
  572.     {
  573.     l=0;
  574.     while(l<ll)
  575.         {
  576.         if (Read(f,flag,2)!=2) return(0);
  577.         bf[l++]=flag[1];
  578.         if (flag[0]<0)
  579.             {
  580.             for(i=0 ; i<-flag[0] ; i++) bf[l++]=flag[1];
  581.             }    
  582.         else
  583.             {
  584.             i=flag[0];
  585.             if (i>0) if (Read(f,bf+l,i)!=i) return(0);
  586.             l+=i;
  587.             }
  588. #ifdef DEBUG
  589. sprintf(dbg,"ll=%ld l=%ld flag0=%ld flag1=%lx\n",ll,l,flag[0],flag[1]);
  590. write_dbg(dbg);
  591. #endif
  592.         }
  593.     }
  594. return(1);
  595.  
  596. /************************************************
  597.  ** elimina una texture map dall'elenco        **
  598.  ************************************************
  599.  *** INPUT :                    *
  600.  * in -> valore >0 restituito da display3d.    *
  601.  * id -> valore >0 restituito da newtmap.    *
  602.  *** OUTPUT:                    *
  603.  * nessuno.                    *
  604.  ************************************************/
  605. void GD_rmtmap(in,id)
  606. REG(a0)struct ambient3d *in;
  607. REG(a1)struct buftmap *id;
  608. {
  609.  
  610.  
  611. if (id==NULL OR in->graf->a_tmap==NULL) return((void)0);
  612. if (id->chunky!=NULL)
  613.     {
  614.     FreeMem(id->chunky,id->lung);
  615.     id->chunky=0L;
  616.     }
  617. }
  618.  
  619.  
  620. /************************************************
  621.  ** crea e inizializza una nuova struttura     **
  622.  ** oggetto e tutte le sue sottostrutture.     **
  623.  ** Lo fa diventare l'attuale.               **
  624.  ************************************************
  625.  *** INPUT :                        * 
  626.  * in -> valore > 0 restituito da display3d.    *
  627.  * name -> puntatore a stringa con nome oggetto.*
  628.  * pol  -> n# totale poligoni nell'oggetto.     *
  629.  * vert -> n# totale vertici nell'oggetto.      *
  630.  *** OUTPUT:                    *
  631.  * > 0 tutto ok, rende n# identificatore oggetto*
  632.  * =0 errore, operazione fallita.        * 
  633.  ************************************************/
  634. long int GD_newobj(in,name,pol,vert)
  635. REG(a0)struct ambient3d *in;
  636. REG(a1)char *name;
  637. REG(d0)long int pol;
  638. REG(d1)long int vert;
  639. {
  640. long int i,id,lv,lv1;
  641. struct objectnode *ob;
  642. struct vert1 *vc;
  643. struct polygon *pl;
  644. char *n;
  645.  
  646. id=in->total_objects;
  647. if (id>MAXOBJECT) return(0);
  648. if (vert>MAXVERT) return(0);
  649.  
  650. in->total_objects+=1;
  651.  
  652. in->attuale=id;
  653. ob=pobj(in);
  654.  
  655. n=ob->name;
  656.  
  657. i=0;
  658. while(i<21 OR name[i]!=0x00) n[i]=name[i++];
  659. n[i]=0x00;
  660.  
  661. /** inizializzo valori di default */
  662. ob->numpolys=pol;
  663. ob->numverts=vert;
  664. ob->vorig=0;
  665. ob->vlocal=0;
  666. ob->vcamera=0;
  667. ob->polys=0;
  668. ob->state=1;
  669. ob->shade=in->view_mode;
  670. ob->trasf=1;
  671.  
  672. /* definisco origine oggetto alle coordinate 0,0,0 */
  673. ob->worldposx=0;
  674. ob->worldposy=0;
  675. ob->worldposz=0;
  676.  
  677. lv=vert*sizeof(Svertex);
  678. lv1=vert*sizeof(Svert1);
  679.  
  680. n=(char *)AllocMem(lv,NULL);
  681. if (n<=(char *)NULL)
  682.     {
  683.     GD_deleteobject(in);
  684.     return(0);
  685.     }
  686. ob->vorig=(struct vertex *)n;
  687.  
  688. n=(char *)AllocMem(lv,NULL);
  689. if (n<=(char *)NULL)
  690.     {
  691.     GD_deleteobject(in);
  692.     return(0);
  693.     }
  694. ob->vlocal=(struct vertex *)n;
  695.  
  696. n=(char *)AllocMem(lv1,NULL);
  697. if (n<=(char *)NULL)
  698.     {
  699.     GD_deleteobject(in);
  700.     return(0);
  701.     }
  702. ob->vcamera=(struct vert1 *)n;
  703.  
  704. vc=ob->vcamera;
  705. for(i=0 ; i<vert ; i++) vc[i].npol=0;
  706.  
  707. n=(char *)AllocMem(pol*sizeof(Spolygon),NULL);
  708. if (n<=(char *)NULL)
  709.     {
  710.     GD_deleteobject(in);
  711.     return(0);
  712.     }
  713. ob->polys=(struct polygon *)n;
  714.  
  715. pl=ob->polys;
  716. for(i=0 ; i<pol ; i++)
  717.     {
  718.     pl[i].vertexlist0=-1;
  719.     pl[i].vertexlist1=-1;
  720.     pl[i].vertexlist2=-1;
  721.     pl[i].vertexlist3=-1;
  722.     }
  723.  
  724. ob->id=in->numero;
  725. in->numero+=1;
  726. in->max_polys+=ob->numpolys;
  727.  
  728. return(ob->id);
  729.  
  730. }
  731.  
  732. /************************************************
  733.  ** elimina oggetto attuale e libera la memoria**
  734.  ************************************************
  735.  *** INPUT :                        * 
  736.  * in -> valore > 0 restituito da display3d.    *
  737.  *** OUTPUT:                    *
  738.  * nessuno.                    *
  739.  ************************************************/
  740. void GD_deleteobject(in)
  741. REG(a0)struct ambient3d *in;
  742. {
  743. struct objectnode *ob;
  744. char *s,*d;
  745. long int sob,i,i1;
  746.  
  747. if (in->total_objects<=NULL) return(0);
  748.  
  749. sob=sizeof(Sobjectnode);
  750. ob=pobj(in);
  751.  
  752. in->max_polys-=ob->numpolys;
  753.  
  754. i=sizeof(Svertex)*ob->numverts;
  755. i1=sizeof(Svert1)*ob->numverts;
  756.  
  757. if (ob->vorig!=NULL) FreeMem(ob->vorig,i);
  758. if (ob->vlocal!=NULL) FreeMem(ob->vlocal,i);
  759. if (ob->vcamera!=NULL) FreeMem(ob->vcamera,i1);
  760. if (ob->polys!=NULL) FreeMem(ob->polys,sizeof(Spolygon)*ob->numpolys);
  761.  
  762. in->total_objects-=1;
  763. if (in->attuale>=in->total_objects)
  764.     {
  765.     in->attuale=in->total_objects-1;
  766.     if (in->attuale<NULL) in->attuale=0;
  767.     return(0);
  768.     }
  769.  
  770. /* elimino i dati dell'oggetto */
  771. /*cmem(ob+sob,ob,mul(in.total_objects-in.attuale-1,sob))*/
  772. /** !!!attenzione!!! questa routin in questo caso e' ok ***/
  773. /** ma se si devono spostare aree sovrapposte non va piu' bene **/ 
  774. d=(char *)ob;
  775. s=(char *)ob+sob;
  776. for(i=0 ; i<(in->total_objects-in->attuale)*sob ; i++) d[i]=s[i];
  777.  
  778. }
  779.  
  780. /************************************************
  781.  ** inserisce un vertice nell'oggetto corrente.**
  782.  ************************************************
  783.  *** INPUT :                        * 
  784.  * in -> valore > 0 restituito da display3d.    *
  785.  * num -> numero indice del vertice da inserire *
  786.  *        (#1 = 0, #2 = 1, ...).         *
  787.  * x   -> valore coordinata x vertice           *
  788.  *        (in FIXPOINT)                *
  789.  * y   -> valore coordinata y vertice           *
  790.  *        (in FIXPOINT)                *
  791.  * z   -> valore coordinata z vertice           *
  792.  *        (in FIXPOINT)                *
  793.  *** OUTPUT:                    *
  794.  * > 0 tutto ok, vertice inserito.        *
  795.  * = 0 operazione fallita.            *
  796.  *** NOTA  :                    *
  797.  * Se si cerca di inserire un vertice con indice*
  798.  * maggiore del numero di vertici definiti per  *
  799.  * l'oggetto l'operazione fallira'.        *
  800.  ************************************************/
  801. long int GD_addobjvertex(in,num,x,y,z)
  802. REG(a0)struct ambient3d *in;
  803. REG(d0)long int num;
  804. REG(d1)long int x;
  805. REG(d2)long int y;
  806. REG(d3)long int z;
  807. {
  808. struct objectnode *obj;
  809. struct vertex *vl,*vo;
  810.  
  811. obj=pobj(in);
  812.  
  813. vl=obj->vlocal;
  814. vo=obj->vorig;
  815.  
  816. if (num+1>obj->numverts) return(0);
  817. if (num<NULL) return(0);
  818.  
  819. vl[num].x=x;
  820. vo[num].x=x;
  821. vl[num].y=y;
  822. vo[num].y=y;
  823. vl[num].z=z;
  824. vo[num].z=z;
  825.  
  826. return(1);
  827. }
  828.  
  829. /************************************************
  830.  ** inserisce un poligono all'oggetto corrente **
  831.  ** se p4=-1 allora poligono a 3 vertici.      **
  832.  ************************************************
  833.  *** INPUT :                        * 
  834.  * in -> valore > 0 restituito da display3d.    *
  835.  * num -> numero indice del poligono da inserire*
  836.  *        (#1 = 0, #2 = 1, ...).        *
  837.  * p1  -> numero indice primo punto pol. su     *
  838.  *        elenco vertico oggetto.        *
  839.  * p2  -> numero indice secondo punto pol. su   *
  840.  *        elenco vertico oggetto.        *
  841.  *        (=-1 allora poligono a un vertice).   *
  842.  * p3  -> numero indice terzo punto pol. su     *
  843.  *        elenco vertico oggetto.        *
  844.  *        (=-1 allora poligono a due vertici).  *
  845.  * p4  -> numero indice quarto punto pol. su    *
  846.  *        elenco vertico oggetto .        *
  847.  *        (=-1 allora poligono a tre vertici).  *
  848.  *** OUTPUT:                    *
  849.  * > 0 tutto ok, poligono inserito.        *
  850.  * = 0 operazione fallita.            *
  851.  *** NOTA  :                    *
  852.  * Se si cerca di inserire un poligono con      *
  853.  * indice maggiore del numero di poligoni       *
  854.  * definiti per l'oggetto l'operazione fallira'.*
  855.  ************************************************/
  856. long int GD_addobjpoly(in,num,p1,p2,p3,p4)
  857. REG(a0)struct ambient3d *in;
  858. REG(d0)long int num;
  859. REG(d1)long int p1;
  860. REG(d2)long int p2;
  861. REG(d3)long int p3;
  862. REG(d4)long int p4;
  863. {
  864. struct objectnode *obj;
  865. struct polygon *poly;
  866. struct vertex *vert;
  867. long int t;
  868.  
  869. obj=pobj(in);
  870. poly=obj->polys;
  871. vert=obj->vorig;
  872.  
  873. if (num+1>obj->numpolys) return(0);
  874. if (num<NULL) return(0);
  875.  
  876. t=1;
  877. if (p1<NULL) return(0);
  878. if (p2>=NULL) t++;
  879. if (p3>=NULL) t++;
  880. if (p4>=NULL) t++;
  881.  
  882. poly[num].numpoints=t;
  883. poly[num].twosided=1;      /* default poligono a due facce */
  884. poly[num].visible=1;
  885. poly[num].clipped=0;
  886. poly[num].active=1;
  887. poly[num].vertexlist0=p1;
  888. poly[num].ptmap.dtmap=0;
  889. if (t>1) poly[num].vertexlist1=p2;
  890. if (t>2) poly[num].vertexlist2=p3;
  891. if (t>3) poly[num].vertexlist3=p4;
  892.  
  893. return(1);
  894. }
  895.  
  896. /************************************************
  897.  ** modifica i parametri dell'oggetto attuale  **
  898.  ************************************************
  899.  *** INPUT :                    *
  900.  * in -> valore > 0 restituito da display3d.    *
  901.  * new -> puntatore a array di strutture tag3d  *
  902.  *        con nuovi parametri per oggetto     *
  903.  *** OUTPUT:                    *
  904.  * = 0 nessuna variazione.            *
  905.  * > 0 numero di variazioni effettuate.        *
  906.  ************************************************/
  907. long int GD_modobj(in,new)
  908. REG(a0)struct ambient3d *in;
  909. REG(a1)struct tag3d *new;
  910. {
  911. long int ft,ris,i,md,ct;
  912. struct objectnode *obj;
  913.  
  914. ris=0;
  915. ct=0;
  916. if (in->total_objects==NULL) return(0);
  917. obj=pobj(in);
  918.  
  919. while(new[ct].tipo!=END_T AND ct<100)
  920.     {
  921.     ft=new[ct].tipo;
  922.     i=new[ct].val;
  923.     switch(ft)
  924.         {
  925.         case(MO_STATE):
  926.         /* attiva(1) o disattiva(0) l'oggetto attuale */
  927.             obj->state=i;
  928.             ris++;
  929.             break;
  930.  
  931.         case(MO_VMODE):
  932.         /* cambia il modo di visualizzazione */
  933.             md=0x0F & i;
  934.             if (md==WIREF OR md==SOLID OR md==FLAT OR md==GORAUD) obj->shade=i;
  935.             ris++;    
  936.             break;    
  937.  
  938.         }
  939.     ct++;
  940.     }
  941.  
  942. return(ris);
  943. }
  944.  
  945. /************************************************
  946.  ** modifica i parametri di un poligono        **
  947.  ** dell'oggetto attuale.               **
  948.  ************************************************
  949.  *** INPUT :                    *
  950.  * in -> valore > 0 restituito da display3d.    *
  951.  * new -> puntatore a array di strutture tag3d  *
  952.  *        con nuovi parametri per poligono.     *
  953.  *** OUTPUT:                    *
  954.  * = 0 nessuna variazione.            *
  955.  * > 0 numero di variazioni effettuate.        *
  956.  ************************************************/
  957. long int GD_modpoly(in,new)
  958. REG(a0)struct ambient3d *in;
  959. REG(a1)struct tag3d *new;
  960. {
  961. long int ris,i,ct,ft,n_pol;
  962. struct grafica *graf;
  963. struct objectnode *obj;
  964. struct polygon *a_poly,*poly;
  965. struct buftmap *btm;
  966. struct vtmap *vt;
  967.  
  968. graf=(struct grafica *)in->graf;
  969. obj=pobj(in);
  970. a_poly=obj->polys;
  971. poly=&a_poly[0];
  972.  
  973. ct=0;
  974. ris=0;
  975. n_pol=0;
  976. while(new[ct].tipo!=END_T AND ct<1000)
  977.     {
  978.     ft=new[ct].tipo;
  979.     i=new[ct].val;
  980.     switch(ft)
  981.         {
  982.         case(MP_POLY):
  983.         /* seleziona il poligono di cui modificare le caratteristiche (def. 0) */
  984.         if (i<obj->numpolys)
  985.             {
  986.             n_pol=i;
  987.             poly=&a_poly[n_pol];
  988.             ris++;
  989.             }
  990.         break;
  991.  
  992.         case(MP_ACTIV):
  993.         /* attiva(1) o disattiva(0) il poligono selezionato */
  994.         poly->active=i;
  995.         ris++;
  996.         break;
  997.         
  998.         case(MP_COLOR):
  999.         /* nuovo colore per poligono selezionato */
  1000.         if (i<graf->n_color)
  1001.             {
  1002.             poly->color=i;
  1003.             ris++;
  1004.             }
  1005.         break;
  1006.  
  1007.         case(MP_2SIDE):
  1008.         /* setta a 2(1) o 1(0) faccia il poligono selezionato */        
  1009.         if (poly->numpoints>2)
  1010.             {
  1011.             poly->twosided=i;
  1012.             ris++;
  1013.             }        
  1014.         break;
  1015.  
  1016.         case(MP_TMAP):
  1017.         /* aggiunge una texture map al poligono ,.val deve puntare alla */
  1018.         /* struttura buftmap che la descrive */
  1019.         if (i!=NULL AND poly->numpoints>2)
  1020.             {
  1021.             poly->ptmap.dtmap=(struct buftmap *)i;
  1022.             ris++;
  1023.             }
  1024.         break;
  1025.  
  1026.         case(MP_VTMAP):
  1027.         /* setta vertici su texture map, .val deve puntare a struttura vtmap */
  1028.         /* tale struttura deve avere definiti almeno lo stesso n# di vertici del */
  1029.         /* poligono alla quale verra' assegnata */
  1030.         if (poly->numpoints>2)            
  1031.             {
  1032.             vt=(struct vtmap *)i;
  1033.             poly->ptmap.u1=vt->x1;
  1034.             poly->ptmap.v1=vt->y1;
  1035.             poly->ptmap.u2=vt->x2;
  1036.             poly->ptmap.v2=vt->y2;
  1037.             poly->ptmap.u3=vt->x3;
  1038.             poly->ptmap.v3=vt->y3;
  1039.             poly->ptmap.u4=vt->x4;
  1040.             poly->ptmap.v4=vt->y4;
  1041.             ris++;
  1042.             }
  1043.         break;
  1044.         
  1045.         case(MP_VTAUTO):
  1046.         /* setta i vertici su texture map in modo automatico, riempie tutto il */
  1047.         /* poligono con tutta la texture.*/
  1048.         if (poly->numpoints>2 AND poly->ptmap.dtmap!=NULL)
  1049.             {
  1050.             btm=poly->ptmap.dtmap;
  1051.             poly->ptmap.u1=0;
  1052.             poly->ptmap.v1=0;
  1053.             poly->ptmap.u2=btm->larg;
  1054.             poly->ptmap.v2=0;
  1055.             poly->ptmap.u3=btm->larg;
  1056.             poly->ptmap.v3=btm->alt;
  1057.             poly->ptmap.u4=0;
  1058.             poly->ptmap.v4=btm->alt;
  1059.             ris++;
  1060.             }
  1061.         break;
  1062.         }
  1063.     ct++;
  1064.     }
  1065.  
  1066. return(ris);
  1067. }
  1068.  
  1069. /************************************************
  1070.  ** cambia le caratteristiche di un poligono.  **
  1071.  ************************************************
  1072.  *** INPUT :                        * 
  1073.  * in -> valore > 0 restituito da display3d.    *
  1074.  * num -> numero indice del poligono da variare *
  1075.  *        (#1 = 0, #2 = 1, ...).        *
  1076.  * color -> colore base per oggetto, in caso di *
  1077.  *          visualizzazione flat usera i colori *
  1078.  *          successivi a questo per sfumare.    *
  1079.  * twoside -> indica se poligono a 2 facce (1) o*
  1080.  *            a una faccia (0).            *
  1081.  *            Se a due facce sara' visibile solo*
  1082.  *          la faccia frontale.        *
  1083.  *** OUTPUT:                    *
  1084.  * > 0 tutto ok, poligono modificato.        *
  1085.  * = 0 operazione fallita.            *
  1086.  *** NOTA  :                    *
  1087.  * Se si cerca di modificare un poligono con    *
  1088.  * indice maggiore del numero di poligoni       *
  1089.  * definiti per l'oggetto l'operazione fallira'.*
  1090.  ************************************************/
  1091. long int GD_cattpoly(in,num,color,twoside)
  1092. REG(a0)struct ambient3d *in;
  1093. REG(d0)long int num;
  1094. REG(d1)long int color;
  1095. REG(d2)long int twoside;
  1096. {
  1097. struct objectnode *obj;
  1098. struct polygon *poly;
  1099. long int c;
  1100.  
  1101. obj=pobj(in);
  1102. poly=obj->polys;
  1103.  
  1104. if (num+1>obj->numpolys) return(0);
  1105. if (num<NULL) return(0);
  1106.  
  1107. if (poly[num].numpoints>2) poly[num].twosided=twoside;
  1108.  
  1109. c=color;
  1110. if (c>in->graf->n_color) c=in->graf->n_color-1;
  1111. poly[num].color=c;
  1112.  
  1113. return(1);
  1114. }
  1115.  
  1116. /************************************************
  1117.  ** Setta come attuale l'oggetto di cui e'dato **
  1118.  ** l'identificativo.                   **
  1119.  ************************************************
  1120.  *** INPUT :                        * 
  1121.  * in -> valore > 0 restituito da display3d.    *
  1122.  * num -> identificativo oggetto da settare.    * 
  1123.  *** OUTPUT:                    *
  1124.  * > 0 tutto ok,                 * 
  1125.  * = 0 operazione fallita.            *
  1126.  ************************************************/
  1127. long int GD_setobj(in,num)
  1128. REG(a0)struct ambient3d *in;
  1129. REG(d0)long int num;
  1130. {
  1131. long int ris,buf;
  1132. struct objectnode *obj;
  1133.  
  1134. ris=0;
  1135. if (num==0) return(0);
  1136. buf=in->attuale;
  1137. obj=resetobj(in);
  1138. while ((obj!=0 AND ris==0))
  1139.     {
  1140.     if (num==obj->id) 
  1141.         {
  1142.         ris=1;    
  1143.         }
  1144.     else    
  1145.         {
  1146.         obj=nextobj(in);
  1147.         }
  1148.     }
  1149.  
  1150. if (ris==NULL) in->attuale=buf;
  1151. return(ris);
  1152.  
  1153. }
  1154.  
  1155. /************************************************
  1156.  ** Ritorna l'identificativo dell'oggetto      **
  1157.  ** attuale.                       **
  1158.  ************************************************
  1159.  *** INPUT :                        * 
  1160.  * in -> valore > 0 restituito da display3d.    *
  1161.  *** OUTPUT:                    *
  1162.  * >0 tutto ok, valore identificativo.        *
  1163.  * = 0 operazione fallita.            *
  1164.  ************************************************/
  1165. long int GD_getobj(in)
  1166. REG(a0)struct ambient3d *in;
  1167. {
  1168. struct objectnode *obj;
  1169.  
  1170. obj=pobj(in);
  1171.  
  1172. return(obj->id);
  1173.  
  1174. }
  1175.  
  1176. /************************************************
  1177.  ** aggiorna tutti i dati precalcolati dello   **
  1178.  ** oggetto attuale.                   **
  1179.  ************************************************
  1180.  *** INPUT :                        * 
  1181.  * in -> valore > 0 restituito da display3d.    *
  1182.  *** OUTPUT:                    *
  1183.  * nessuno.                    *
  1184.  *** NOTA :                    *
  1185.  * Il ricalcolo si effettua solo se l'oggetto e'*
  1186.  * stato effettivamente modificato.        *
  1187.  ************************************************/
  1188. void GD_recalcobj(in)
  1189. REG (a0)struct ambient3d *in;
  1190. {
  1191. struct objectnode *obj;
  1192.  
  1193. obj=pobj(in);
  1194.  
  1195. if (in->total_objects>NULL AND obj->trasf!=NULL OR in->agg_all!=NULL)  
  1196.     {
  1197.     if (obj->trasf & 0x01!=NULL) aggobj(in);
  1198.     }
  1199.  
  1200. }
  1201.  
  1202. /***************** FINE ROUTIN USABILI ESTERNAMENTE ********************/
  1203.  
  1204.